package cn.com.blink.day0522;

import cn.com.blink.bean.SampleData;
import cn.com.blink.bean.Track;
import org.junit.Assert;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toSet;


/**
 * Created by liuzh on 2017/5/22.
 */
public class StreamTest {

    //从外部迭代到内部迭代
    @Test
    public void test1() {
        List<Integer> integerList = new ArrayList<>();
        integerList.add(10);
        integerList.add(20);
        integerList.add(22);
        integerList.add(30);

        //计算大于20的数目(亦可通过迭代器实现)
        int count = 0;
        for (int i : integerList) {
            if (i > 20) count++;
        }
        System.out.println("integerList元素大于20的数目:" + count);

        //stream api方式：创建集合的配方而不是创建一个新的集合
        long count1 = integerList
                .stream()
                .filter(integer -> integer > 20)
                .count();
        System.out.println("integerList元素大于20的数目:" + count1);
        //惰性求值方法filter 及早求值方法count
    }

    //collect
    @Test
    public void testCollect() {
        List<String> collected = Stream
                .of("a", "b", "c")
                .collect(Collectors.toList());
        Assert.assertEquals(Arrays.asList("a", "b", "c"), collected);
    }

    //map 将一组字符串转换成大写
    @Test
    public void testMap() {
        List<String> src = Arrays.asList("a", "b", "hello");
        List<String> collected = new ArrayList<>();
        for (String string : src) {
            collected.add(string.toUpperCase());
        }
        Assert.assertEquals(Arrays.asList("A", "B", "HELLO"), collected);

        List<String> collected_ = src.stream()
                .map(s -> s.toUpperCase())//映射
                .collect(Collectors.toList());

        Assert.assertEquals(collected_, collected);
    }

    //filter 找出一组字符串中以数字开头的字符串
    @Test
    public void testFilter() {
        List<String> src = Arrays.asList("a", "1b", "hello2");
        List<String> collected = new ArrayList<>();
        for (String string : src) {
            if (Character.isDigit(string.charAt(0))) {
                collected.add(string);
            }
        }
        Assert.assertEquals(Arrays.asList("1b"), collected);

        List<String> collected_ = src.stream()
                .filter(s -> Character.isDigit(s.charAt(0)))
                .collect(Collectors.toList());
        Assert.assertEquals(collected_, collected);
    }

    //flatMap 合并两个列表
    @Test
    public void testFlatMap() {
        List<Integer> src0 = Arrays.asList(1, 2, 3);
        List<Integer> src1 = Arrays.asList(3, 4, 5);
//        List<List<Integer>> list = Stream.of(src0, src1).collect(Collectors.toList());
        List<Integer> together = Stream.of(src0, src1)
                .flatMap(integers -> integers.stream())//映射，与map区别：只能映射为stream,返回的是合并流
                .collect(Collectors.toList());
        together.forEach(System.out::println);
    }

    //max & min
    @Test
    public void testMaxMin() {
        //查找最短曲目
        List<Track> tracks = Arrays.asList(
                new Track("Bakai", 524),
                new Track("Violets for Your Furs", 378),
                new Track("Time was", 451));
        Track shortestTrack = tracks.stream().min(Comparator.comparing(track -> track.getLength())).get();
        Track longestTrack = tracks.stream().max(Comparator.comparing(track -> track.getLength())).get();
        System.out.println(shortestTrack);
        System.out.println(longestTrack);
    }

    //reduce reduce操作可以实现从一组值中生成一个值
    @Test
    public void testReduce() {
        int count = Stream.of(1, 2, 3).reduce(0, (integer, integer2) -> integer + integer2);
        Assert.assertEquals(6, count);
    }

    @Test
    public void test() {
        Set<String> origins = SampleData.aLoveSupreme
                .getMusicians()
                .filter(artist -> artist.getName().startsWith("The"))
                .map(artist -> artist.getNationality())
                .collect(toSet());
        origins.forEach(System.out::println);
    }
    /**
     * 内部迭代将更多的控制权交给了集合类
     * 和Iterator类似，Stream是一种内部迭代方式
     * 将Lambda表达式和Stream上的方法结合起来，可以完成很多常见的集合操作
     */
}
